<!--
  上传组件（向后端服务器获取表单形式， 直传到oss）

  @author terrfly
  @site https://www.jeequan.com
  @date 2022/01/14 12:14 
-->
<template>
  <div style="">
    <!--  capture=undefined ： 手机可选择本地图片，     删除该属性，则手机上传无法读取相册 ， 直接调起相机。 https://github.com/vueComponent/ant-design-vue/issues/5986  -->
    <a-upload
      v-model:fileList="vdata.fileListArray"
      :action="vdata.action"
      :beforeUpload="beforeUploadFunc"
      :headers="vdata.headers"
      :data="vdata.formParams"
      :list-type="vdata.listType"
      :showUploadList="props.showUploadList"
      :multiple="true"
      :accept="vdata.accept"
      :capture="undefined"
      :disabled="props.disabled"
      @preview="previewFileFunc"
      @change="handleChange"
    >
      <div v-if="!props.disabled">
        <div v-if="vdata.fileListArray.length < 8">
          <plus-outlined />
          <div class="ant-upload-text">点此上传</div>
        </div>
      </div>
    </a-upload>

    <!-- ！！！ 本地测试！！！  -->
    <!-- <button @click="() => emit('update:src', 'https://jeepaypublic.oss-cn-beijing.aliyuncs.com/applyment/4f0f1ae8-d3e5-46b0-a75e-7d49b31827b1.jpg')">测试</button> -->
  </div>
</template>

<script setup lang="ts">
import { Upload } from 'ant-design-vue'
import appConfig from '@/config/appConfig'
import storage from '@/utils/jeepayStorageWrapper'
import { reactive, defineProps, getCurrentInstance, onMounted, nextTick, watch } from 'vue'
import { API_URL_UPLOAD_SINGLE_FILE_URL, $getUploadFormParams, $orcScan } from '@/api/manage'
import { sm4DecryptByResData } from '@/utils/encryptUtil'
const { $infoBox, $viewerApi } = getCurrentInstance()!.appContext.config.globalProperties

// 定义 父组件传参
const props = defineProps({
  showUploadList: { type: Boolean, default: true }, // 是否显示上传的列表， 一般都需要显示，  比如头像需要自定义的话那么则不需要显示，并且按钮常显
  fileList: { type: String, default: '' }, // 双向绑定  文件地址
  bizType: { type: String, default: '' }, // 业务类型
  fileType: { type: String, default: 'img' }, // img or file
  accept: { type: String, default: null }, // 上传文件的accept
  uploadMode: { type: String, default: 'formRedirect' }, // 上传方式： formRedirect 先获取form表单地址直传oss,  file：上上传到本地后端服务器在上传到oss方式。
  ocrType: { type: String, default: null }, // orc类型如果存在值则上传成功后自动调起ORC识别功能
  imgSize: { type: Number, default: localStorage.getItem('uploadImgSize') || 2 }, // 上传图片大小限制  优先获取本地存储 
  listType: { type: String, default: 'picture' }, // 上传列表的内建样式 默认picture
  disabled: { type: Boolean, default: false }, // 上传列表的内建样式 默认picture
})

// 父组件通讯函数
const emit = defineEmits(['update:fileList', 'change', 'ocrScan'])

// 定义响应式数据
const vdata: any = reactive({
  action: '', // 文件form表单请求地址
  fileList: [], // 全部文件集合
  formParams: {}, // 上传参数
  headers: {}, // 放入token
  formReqFileUrl: '', // 第一次的form请求的图片数据， 如果存在则使用该地址， 否则使用文件上传的响应地址。
  accept: null, //上传文件的accept
  listType: '', // 上传列表的内建样式
  fileListArray: []
})

onMounted(() => {
  if (props.listType) {
    vdata.listType = props.listType
  }

  // 处理 accept
  if (!props.accept && props.fileType == 'img') {
    vdata.accept = 'image/*' // 所有的图片格式
  } else {
    vdata.accept = props.accept
  }

})

function getFileName(name) {
  if (!name) {
    return name
  }

  return name.substring(name.lastIndexOf('/') + 1)
}

// 上传回调
function handleChange(info) {
  if (info && info.file && info.file.status == 'removed') {
    console.log('remove')
    emit('update:fileList', vdata.fileListArray.map(v => v.url).join(','))
    return
  }

  // 上传成功
  if (info && info.file && info.file.status == 'done') {
    let successImgUrl = vdata.formReqFileUrl
    // 读取响应结果的值
    if (!successImgUrl) {
      // 如果包含code 并且 不是0 ： 本系统返回的错误信息。
      if (info.file.response && info.file.response.code != 0) {
        return $infoBox.message.error(info.file.response.msg)
      }

      successImgUrl = info.file.response.encryptData
        ? sm4DecryptByResData(info.file.response.encryptData)
        : info.file.response.data
    }

    info.file.url = successImgUrl

    console.log('done', vdata.fileListArray)
    emit('update:fileList', vdata.fileListArray.map(v => v.url).join(','))
  }
}

// 上传图片前的校验
function beforeUploadFunc(file) {
  // 拦截操作 如果传入imgSize 会对图片大小进行校验
  if (props.bizType === 'applyment') {
    const flag = file.size / 1024 / 1024 < (getLocationImgSize() || props.imgSize)
    if (!flag) {
      $infoBox.message.error(`上传图片大小不能超过${getLocationImgSize() || props.imgSize}M`)
      return flag || Upload.LIST_IGNORE
    }
  }

  if (props.uploadMode == 'formRedirect') {
    // form表单方式
    // 请求获取form参数
    return $getUploadFormParams(file, props.bizType).then((res) => {
      if (res.formActionUrl == 'LOCAL_SINGLE_FILE_URL') {
        // 本地方式
        localUploadResetInfo()
      } else {
        vdata.action = res.formActionUrl // action
        vdata.formParams = res.formParams //表单组件
        vdata.formReqFileUrl = res.ossFileUrl
      }
    }).catch(() => {
      return Upload.LIST_IGNORE
    })
  }

  // file文件方式
  return Promise.resolve((params) => {
    localUploadResetInfo()
  })
}

// 预览图片
function previewFileFunc(file) {
  if (props.fileType == 'img') {
    $viewerApi({ images: [file.url] })
  }
}

// 本地上传的方式，需要设置的form和header等信息
function localUploadResetInfo() {
  //action
  vdata.action = API_URL_UPLOAD_SINGLE_FILE_URL

  // token
  vdata.headers[appConfig.ACCESS_TOKEN_NAME] = storage.getToken()

  // params
  vdata.formParams = { bizType: props.bizType }
}

function ocrFunc(url) {
  if (!props.ocrType) {
    return false
  }

  $orcScan(url, props.ocrType).then((res) => {
    $infoBox.message.success('图片识别成功，已自动回填内容，请检查核对')
    emit('ocrScan', res)
  })
}
// 移动端 地址栏传参解析
function getLocationImgSize() {
  let params = {} as any
  let href = window.location.href
  href = href.substring(href.indexOf('?') + 1)
  let arr = href.split('&')
  arr.forEach(item => {
    let a = item.split('=')
    params[a[0]] = a[1]
  })
  console.log('params.uploadImgSize', params.uploadImgSize)
  console.log('href', href)

  if (params.uploadImgSize) return params.uploadImgSize
  return false
}
watch(() => props.fileList, (old: any, newD: any) => {
  covertFileList(props.fileList)
})
// 图片地址拼接为ant-upload组件需要的列表数据
function covertFileList(fileList) {
  const newItems = [] as any
  nextTick(() => {
    if (fileList) {
      fileList.split(',').forEach((url) => {
        if (!url) return
        newItems.push({ url })
      })
    }

    vdata.fileListArray = newItems
  })

}

</script>
<style scoped lang="less">
/deep/ .ant-upload-list-item-name {
  flex: auto !important;
}
</style>
